Deno press

Or the script that makes this website possible

The script

import * as md6 from 'https://deno.land/x/md6/mod.ts'

// # Make dir
await Deno.mkdir("./public", { recursive: true });

// # Copy css and assets
await Deno.run({ cmd: ["cp", "-r", "./script/css", "./public/"] });
await Deno.run({ cmd: ["cp", "-r", "./script/assets", "./public/"] });

// # Make Pages
// ## Get layout
const layoutHtml = await Deno.readTextFile("./script/layout.html");

// ## Get all md files
const tree = Deno.run({ cmd: ["tree", "-fin", "blog/"], stdout: "piped" });
const tree_output = new TextDecoder().decode(await tree.output());
const files = tree_output
  .split("\n")
  .slice(1, -3)
  .filter((f) => f.endsWith(".md"))
  .map((f) => f.split("/"));

// ### Find if path as children
const hasChildren = (path, files) => {
  const node = path.join("/").slice(0, -3) + "/";
  const nodes = files.map((f) => f.join("/"));

  return nodes.some((n) => n.startsWith(node));
};

const mapHasChildren = (paths, files) => {
  return paths.map((p) => {
    return {
      path: p,
      children: hasChildren(p, files),
    };
  });
};

// ### Get all the relative files to make nav
const getRelatives = (file, files) => {
  const parents = files.filter((f) => {
    const good = f[file.length - 2];
    if (good != undefined) {
      return (
        good.endsWith(".md") && f[file.length - 3] == file[file.length - 3]
      );
    } else {
      return false;
    }
  });

  const siblings = files.filter((f) => {
    const good = f[file.length - 1];
    if (good != undefined) {
      return (
        good.endsWith(".md") && f[file.length - 2] == file[file.length - 2]
      );
    } else {
      return false;
    }
  });

  const children = files.filter((f) => {
    const end = file[file.length - 1].slice(0, -3);
    if (f[f.length - 2] != undefined) {
      return f[f.length - 2] == end;
    } else {
      return false;
    }
  });

  const pMap = mapHasChildren(parents, files);
  const sMap = mapHasChildren(siblings, files);
  const cMap = mapHasChildren(children, files);

  return { parents: pMap, siblings: sMap, children: cMap };
};

const makeLinks = (column, files, file) => {
  if (files.length > 0) {
    return `<nav class="column ${column}">
      ${files.map((f) => `
        <a href="/${f.path.slice(1).join("/").slice(0, -3)}.html"
          class="
          ${f.path == file ? "here" : ""}
          ${f.children ? "children" : ""}
          "
        >
          ${f.path[f.path.length - 1].slice(0, -3)}
        </a>`).join("")}
      </nav>`;
  } else {
    return "";
  }
};

// ## Make page for all files
const makePage = async (file, files) => {
  let page = `${layoutHtml}`;

  const { parents, siblings, children } = getRelatives(file, files);

  const parentsLink = makeLinks("parents", parents, file);
  const siblingsLink = makeLinks("siblings", siblings, file);
  const childrenLink = makeLinks("children", children, file);

  const filePath = file.join("/");
  const content = await Deno.readTextFile(filePath);
  const mdContent = md6.toHtml(content);

  page = page.replace("%content%", mdContent);
  page = page.replace("%parents%", parentsLink);
  page = page.replace("%siblings%", siblingsLink);
  page = page.replace("%children%", childrenLink);

  const filePathWrite = `public/${filePath.slice(5, -3)}.html`;

  await Deno.writeTextFile(filePathWrite, page, { create: true });
};

files.forEach((file) => {
  makePage(file, files);
});

// ## Make error page
const page = `${layoutHtml}`
  .replace("%content%", "<h1>You seem lost?</h1>")
  .replace("%parents%", "")
  .replace("%siblings%", "")
  .replace("%children%", "");
await Deno.writeTextFile("public/404.html", page, { create: true });